// Copyright (c) 2014 Dan Nagle. All rights reserved.
//
// Licensed MIT: https://github.com/dannagle/PacketSender-Android
package com.packetsender.android;
import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class Packet implements Comparable<Packet> {
/*
QString name;
QString hexString;
QString fromIP;
QString toIP;
QString errorString;
QByteArray response;
unsigned int repeat;
unsigned int port;
unsigned int fromPort;
QString tcpOrUdp;
unsigned int sendResponse;
void init();
void clear();
QDateTime timestamp;
*/
public String name;
public String fromIP;
public String toIP;
public String errorString;
public byte[] response;
public int repeat;
public int port;
public int fromPort;
public String tcpOrUdp;
public byte[] data;
public long timestamp;
public Packet(String name) {
this.name = name;
}
public static long now()
{
return new Date().getTime();
}
public void nowMe() {
this.timestamp = now();
this.name = Long.toString(this.timestamp);
}
public String timestampString() {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(timestamp);
SimpleDateFormat sdf = new SimpleDateFormat(DataStorage.DATE_FORMAT, Locale.US);
return sdf.format(cal.getTime()).toLowerCase(Locale.US);
}
public Packet() {
this.name = "";
this.tcpOrUdp = "TCP";
this.timestamp = now();
this.fromIP = "192.168.1.23";
this.toIP = "192.168.1.23";
this.fromPort = 50055;
this.port = 50055;
this.data = new byte[10];
this.errorString = "";
}
public Packet duplicate() {
Packet newPacket = new Packet();
newPacket.name = name;
newPacket.fromIP = fromIP;
newPacket.toIP = toIP;
newPacket.errorString = errorString;
newPacket.response = response;
newPacket.repeat = repeat;
newPacket.port = port;
newPacket.fromPort = fromPort;
newPacket.tcpOrUdp = tcpOrUdp;
newPacket.data = new byte[data.length];
System.arraycopy( data, 0, newPacket.data, 0, data.length );
newPacket.timestamp = timestamp;
return newPacket;
}
public String toString()
{
return "name:" + this.name +"\n" +
"tcpudp:" + this.tcpOrUdp + "\n" +
"timestamp:" + this.timestamp+ "\n" +
"fromip:" + this.fromIP + "\n" +
"toip:" + this.toIP + "\n" +
"fromport:" + this.fromPort + "\n" +
"port:" + this.port + "\n" +
"errorString:" + this.errorString + "\n" +
"ascii:" + toAscii() + "\n" +
"hex:" + toHex();
}
public static String toAscii(byte[] data)
{
Packet pkt = new Packet();
pkt.data = data;
return pkt.toAscii();
}
public String toAscii()
{
String returnString = "";
for (int item : this.data)
{
if(item == 0x0A)
{
returnString = returnString + "\\n";
} else if (item == 0x0D) {
returnString = returnString + "\\r";
} else if (item >= 0x20 && item <= 0x7E) {
returnString = returnString + (char) item;
} else {
String hex = Integer.toHexString(item & 0xff);
if(hex.length() == 1) {
hex = "0" + hex;
}
returnString = returnString + "\\" + hex;
}
}
return returnString;
}
private static int iAt(String s, int index) {
if(index < s.length()) {
return (((int) s.charAt(index)) & 0xff);
} else {
return -1;
}
}
private static byte[] toByteArray(List<Byte> list){
byte[] ret = new byte[list.size()];
for(int i = 0;i < ret.length;i++)
ret[i] = list.get(i);
return ret;
}
public static byte[] asciiToBytes(String ascii) {
int val1, val2, val3;
char c1, c2;
List<Byte> bytes = new ArrayList<Byte>();
ascii = ascii.replace("\\r", "\\0d");
ascii = ascii.replace("\\n", "\\0a");
for(int i=0; i < ascii.length(); i++) {
val1 = iAt(ascii, i);
if (val1 >= 0x20 && val1 <= 0x7E) {
if(val1 == (((int) '\\') & 0xff)) {
val2 = iAt(ascii, i+1);
val3 = iAt(ascii, i+2);
if(val2 > -1 && val3 > -1) {
c1 = ascii.charAt(i+1);
c2 = ascii.charAt(i+2);
try {
Log.d("packet", DataStorage.FILE_LINE("c1,c2 " + c1 + "," + c2));
Log.d("packet", DataStorage.FILE_LINE("val2,val3 " + val2 + "," + val3));
val2 = Integer.parseInt((c1 + "") + (c2 + ""), 16) & 0xff;
val3 = 0;
Log.d("packet", DataStorage.FILE_LINE("val2,val3 " + val2 + "," + val3));
bytes.add((byte)(val2 + val3));
} catch (NumberFormatException e) {
Log.d("packet", DataStorage.FILE_LINE("bad conversion"));
}
i += 2;
continue;
}
} else {
val1 = iAt(ascii, i);
bytes.add((byte)(val1));
}
}
}
return toByteArray(bytes);
}
public static void UnitTest_conversions() {
String testS[] = new String[2];
String resultS[] = new String[testS.length];
boolean tohex[] = new boolean[testS.length];
testS[0] = "help\\25";
resultS[0] = "68 65 6c 70 25".toUpperCase(Locale.US);
tohex[0] = true;
testS[1] = "68 65 6c 70 25";
resultS[1] = "help%";
tohex[1] = false;
String test;
for(int i=0; i < testS.length; i++) {
if(tohex[i]) {
test = toHex(asciiToBytes(testS[i]));
} else {
test = toAscii(toBytes(testS[i]));
}
Log.d("packet", DataStorage.FILE_LINE(test + " == " + resultS[i] + " ?"));
if(test.equalsIgnoreCase(resultS[i])) {
//passed
Log.d("packet", DataStorage.FILE_LINE("pass, test " + i));
} else {
Log.d("packet", DataStorage.FILE_LINE("error, " + test.length() + "/" + resultS[i].length()
+ " test " + i + ", got\n"
+ test + "\nexpected:\n" + resultS[i] + "\n"));
}
}
}
public String toHex()
{
return Packet.toHex(this.data);
}
public static String toHex(byte[] bytes) {
StringBuffer hexString = new StringBuffer();
for (int i=0;i<bytes.length;i++)
{
String hex = Integer.toHexString(0xFF & bytes[i]).toUpperCase(Locale.US);
if (hex.length() == 1)
{
// could use a for loop, but we're only dealing with a single byte
hexString.append('0');
}
hexString.append(hex);
hexString.append(' ');
}
return hexString.toString().trim();
}
public int compareTo(Packet that)
{
return this.name.compareTo(that.name);
}
public static byte[] toBytes(String param) {
String delims = "[ ]+";
String[] tokens = param.split(delims);
byte[] returnBytes = new byte[tokens.length];
for (int i=0;i<tokens.length;i++)
{
byte hex = 0;
try {
hex = (byte) (Integer.parseInt(tokens[i], 16) & 0xff );
} catch (NumberFormatException nfe) {
returnBytes[i] = 0;
continue;
}
returnBytes[i] = hex;
}
return returnBytes;
}
}